// === all 7 buttons === //
// 5 clicked buttons :up down go pause stop
// 3 radio buttons: fast normal slow

// === up down === //
class cAllButton {
  cAllButton(int x, int y, String text, handler action) {
    this.x = x;
    this.y = y;
    this.text = text;
    this.action = action;
    colr = #F09B2C;
    enabled = true;
  }

  void checkMouseClick(int mx, int my) {
    if (enabled) {
      if (checkRange(mx, my)) {
        action.exec(this);
      }
    }
  }

  void paint() {
    fill(colr);
    textSize(30);
    text(text, x, y);
  }

  // not in range, return false. in range, return true
  protected boolean checkRange(int mx, int my) {
    if (mx < x || my > y) {
      return false;
    }
    if (mx > (x + XRANGE) || my < (y - YRANGE)) {
      return false;
    }
    // mx, my in range, button is clicked
    setMouseClickCirlce(mx, my);
    return true;
  }

  void enable() {
    enabled = true;
  }

  void disable() {
    enabled = false;
  }

  protected handler action;

  protected int x, y;
  protected String text;
  protected color colr;
  protected boolean enabled;

  SoundFile sound;
};

// button click detect range
final int XRANGE = 120;
final int YRANGE = 40;

// === go pause stop === //
class cbuttonGo extends cAllButton {
  cbuttonGo(int x, int y, String text, handler action) {
    super(x, y, text, action);
  }

  void paint() {
    textSize(80);
    if (enabled) {
      fill(colr);
    } else {
      fill(colr, 60);
    }
    text(text, x, y);
  }
};

class cbuttonPause extends cAllButton {
  cbuttonPause(int x, int y, String text, handler action) {
    super(x, y, text, action);
    colr = #48A719; // green
    paused = false;
    invisible();
    blnk = 0;
  }

  void visible() {
    // if set visible, then must set enble
    visibled = true;
    enabled = true;
  }

  void invisible() {
    // if set invisible, then must set disable
    visibled = false;
    enabled = false;
  }

  void paint() {
    if (visibled) {
      textSize(55);
      if (paused) {
        blnk++;
        if (blnk < 20) {
          fill(#F57474); // red
          text("paused", x, y);
        } else if (blnk < 40) {
          // no action
        } else {
          blnk = 0;
        }
      } else {
        fill(colr);
        text(text, x, y);
      }
    }
  }

  int blnk; // blink
  private boolean visibled;
  boolean paused;
};

class cbuttonStop extends cAllButton {
  cbuttonStop(int x, int y, handler action) {
    super(x, y, "", action); // image button, no text
    invisible();
  }

  void visible() {
    // if set visible, then must set enble
    visibled = true;
    enabled = true;
  }

  void invisible() {
    // if set invisible, then must set disable
    visibled = false;
    enabled = false;
  }

  void paint() { // this is an image button, no text
    if (visibled) {
      image(img, x - 43, y - 86); // fined tuned offset for this image position
    }
  }

  PImage img;
  private boolean visibled;
};

// === 3 radio buttons for 3 speed: fast normal slow
class cradio extends cAllButton {
  cradio(int x, int y, String text, handler action) {
    super(x, y, text, action);
    checked = false;
  }

  void paint() {
    textSize(30);
    fill(colr);
    if (checked) {
      text("*", x - 35, y + 10);
    }
    text(text, x, y);
  }

  void checkMouseClick(int mx, int my) {
    // fast normal slow radio buttons always enabled
    if (checkRange(mx, my)) {
      action.exec(this);
    }
  }

  protected boolean checked;
};

class cradio_fast extends cradio {
  cradio_fast(int x, int y, String text, handler action) {
    super(x, y, text, action);
  }
};

class cradio_normal extends cradio {
  cradio_normal(int x, int y, String text, handler action) {
    super(x, y, text, action);
    checked = true;
  }
};

class cradio_slow extends cradio {
  cradio_slow(int x, int y, String text, handler action) {
    super(x, y, text, action);
    checked = false;
  }
};

// click buttons
cAllButton btnUp = new cAllButton(1490, 54, "up", (cAllButton btn)->ButtonUp(btn));
cAllButton btnDn = new cAllButton(1490, 111, "down", (cAllButton btn)->ButtonDn(btn));
cbuttonGo btnGo = new cbuttonGo(1600, 80, "go", (cAllButton btn)->ButtonGo(btn));
cbuttonPause btnPause = new  cbuttonPause(1605, 520, "pause", (cAllButton btn)->ButtonPause(btn));
cbuttonStop btnStop = new cbuttonStop(1683, 826, (cAllButton btn)->ButtonStop(btn)); // image button, no text

// radio buttons
cradio_fast btnFast =  new cradio_fast(1670, 300, "fast", (cAllButton btn)->ButtonFast(btn));
cradio_normal btnMedium = new cradio_normal(1670, 350, "medium", (cAllButton btn)->ButtonMedium(btn));
cradio_slow btnSlow = new cradio_slow(1670, 400, "slow", (cAllButton btn)->ButtonSlow(btn));

// array of click buttons
// these buttons some cases need disable, some need enable etc.
cAllButton[] clickBtns = {btnUp, btnDn, btnGo, btnPause, btnStop};

// array of radio buttons
// these 3 buttons never disable
cradio[] radioBtns = {btnFast, btnMedium, btnSlow};

// array of all buttons
// for painting purpose
cAllButton[] allBtns = {btnUp, btnDn, btnGo, btnPause, btnFast, btnMedium, btnSlow, btnStop};

void drawallBtns() {
  for (cAllButton i : allBtns) {
    i.paint();
  }
}

void checkMouseClick(int mx, int my) {
  for (cAllButton i : allBtns) {
    i.checkMouseClick(mx, my);
  }
}

// cuz SoundFile can not be created before setup running
// so, button sound file is assigned using this routine
void assignBtnSound() {
  btnUp.sound = sndUp;
  btnDn.sound = sndDn;
  btnGo.sound = sndGo;
  btnPause.sound = sndPause;
  btnFast.sound = sndFast;
  btnMedium.sound = sndMedium;
  btnSlow.sound = sndSlow;
}

// ============ button handlers ===============  //
void ButtonUp(cAllButton btn) {
  if (numPlates < 10) {
    preparePlates(++numPlates);
    playSound(btn.sound);
    println("number of plates = " + numPlates);
  }
}

void ButtonDn(cAllButton btn) {
  if (numPlates > 3) {
    preparePlates(--numPlates);
    playSound(btn.sound);
    println("number of plates = " + numPlates);
  }
}

void ButtonGo(cAllButton btn) {
  for (cAllButton i : clickBtns) {
    i.enabled = false; // up, down, go, pause, stop disalbe
  }
  btnPause.visible(); // pause visible (and will be enable of course)
  btnStop.visible(); // stop visible (and will be enable of course)
  btnPause.paused = false;

  showTask = 1; // start Hanoi show. init to 1 will trigger hanioShow() start
  speedCtrl.resume(); // star show
  playSound(btn.sound);
}

void ButtonPause(cAllButton btn) {
  cbuttonPause btn_ = ((cbuttonPause)(btn));
  btn_.paused = !btn_.paused;
  if (btn_.paused) {
    speedCtrl.pause();
    playSound(btn_.sound);
  } else {
    speedCtrl.resume();
    playSound(btn_.sound);
    delay(200);
    playSound(btn_.sound);
  }
}

void ButtonStop(cAllButton btn) {
  endShowTask();
  // no sound for stop button,
  // you will hear done sound later in hanioShow() default case
}

void commonActionRadioBtn(cAllButton btn) {
  for (cradio i : radioBtns) {
    i.checked = false; // unchedk all button
  }
  ((cradio)btn).checked = true; // check current
  playSound(btn.sound);
}

void ButtonFast(cAllButton btn) {
  commonActionRadioBtn(btn);
  speedCtrl.fast();
}

void ButtonMedium(cAllButton btn) {
  commonActionRadioBtn(btn);
  speedCtrl.medium();
}

void ButtonSlow(cAllButton btn) {
  commonActionRadioBtn(btn);
  speedCtrl.slow();
}
